﻿using Coldairarrow.Business.Base_Manage;
using Coldairarrow.Entity.Base_Manage;
using Coldairarrow.Entity.DomainModels;
using Coldairarrow.Util;
using Coldairarrow.Util.Helper;
using Coldairarrow.Util.Utilities;
using EFCore.Sharding;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Hosting;
using NSwag;
using NSwag.Annotations;
using NSwag.CodeGeneration.CSharp;
using NSwag.CodeGeneration.CSharp.Models;
using NSwag.CodeGeneration.OperationNameGenerators;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
namespace Coldairarrow.Api.Controllers.Base_Manage
{
    [Route("/Base_Manage/[controller]/[action]")]
    [OpenApiTag("BuildSuperAsOpenAPI")]
    public class BuildSuperAsOpenAPICodeController 
    {
        #region DI
        readonly IDbAccessor _db;
        public BuildSuperAsOpenAPICodeController(IHostEnvironment evn, IDbAccessor @db,IBuildSuperCodeBusiness buildSuperCodeBus)
        {
            _buildSuperCodeBus = buildSuperCodeBus;
            _db = @db;
            var projectPath = evn.ContentRootPath;
            _solutionPath = Directory.GetParent(projectPath).ToString();
        }
        readonly string _solutionPath;
        IBuildSuperCodeBusiness _buildSuperCodeBus { get; }

        #endregion

        public class InputSearch
        {
            public string Id { get; set; }

            public string Search { get; set; }
        }
        /// <summary>
        /// 获取api信息列表
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        public async Task<object> GetAPIListAsync([FromBody] InputSearch Input)
        {
            System.Net.WebClient wclient = new System.Net.WebClient();
            try
            {
                var apimodel = await _db.GetIQueryable<Base_Api>().Where(x => x.Id.Equals(Input.Id)).FirstOrDefaultAsync();
                string apiurl = "http://localhost:5000/swagger/v1/swagger.json";
                if (!apimodel.IsNullOrEmpty())
                {
                    //apiurl = apimodel.Url;
                    apiurl = JsonOperateService.FullJsonUrl(@"/swagger.json");
                }
                OpenApiDocument document = await OpenApiDocument.FromJsonAsync(wclient.DownloadString(apiurl));
                wclient.Dispose();
                var settings = new CSharpControllerGeneratorSettings
                {
                    ClassName = "{controller}Controller",
                    CSharpGeneratorSettings =
                {
                Namespace = "MyNamespace",
                },

                    ControllerTarget = CSharpControllerTarget.AspNetCore,
                    ControllerBaseClass = "Microsoft.AspNetCore.Mvc.Controller",
                    //设置多个控制器客户端代码生成
                    OperationNameGenerator=new MultipleClientsFromFirstTagAndOperationIdGenerator(),
                    GenerateDtoTypes=true

                };
                var generator2 = new MultiCSharpControllerGenerator(document, settings);
                var apilist = generator2.GetApiMessage(null, Input.Search);
                //if (!Input.Search.IsNullOrEmpty())
                //{
                //    apilist = apilist.Where(x => x.Tags.Contains(Input.Search)).ToList();
                //}
                var q = apilist.GroupBy(x => x.Tags, (x, y) => new
                {
                    key = x,
                    value = y
                }).ToList();
                var res = new
                {
                    Success = true,
                    Data = q
                };

                return res;
            }
            catch (Exception)
            {
                throw;
            }
        }

        /// <summary>
        /// 首次生成api
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        public async Task<object> BuildCodeAsOpenAPI([FromBody] List<string> list)
        {
            bool IsFirst = true;
            List<Base_ApiList> modellist = new List<Base_ApiList>();
            System.Net.WebClient wclient = new System.Net.WebClient();
            var document = await OpenApiDocument.FromJsonAsync(wclient.DownloadString("http://localhost:5000/swagger/v1/swagger.json"));
            wclient.Dispose();
            var settings = new CSharpControllerGeneratorSettings
            {
                ClassName = "{controller}Controller",
                CSharpGeneratorSettings =
                {
                Namespace = "MyNamespace",
                },

                ControllerTarget = CSharpControllerTarget.AspNetCore,
                ControllerBaseClass = "Microsoft.AspNetCore.Mvc.Controller",
                //设置多个控制器客户端代码生成
                OperationNameGenerator=new MultipleClientsFromFirstTagAndOperationIdGenerator(),
                GenerateDtoTypes=true

            };

            var generator2 = new MultiCSharpControllerGenerator(document, settings);

            //生成实体类文件
            foreach (var t in generator2.GenerateDtoTypes())
            {
                JsonOperateService.WriteMyTypeToEntityFile(t.TypeName, t.Code);
            }

            foreach (var p in list)
            {
                string ControllerClassName = generator2.GetControllerClassName(p);
                var qq = generator2.GenerateAllClientTypes_(p, ControllerClassName, null);
                foreach (var t in qq)
                {
                    string str = string.Empty;
                    str += "using Coldairarrow.Api.Models;";
                    str +="\r\n";
                    str += "using Microsoft.AspNetCore.Mvc;";
                    str +="\r\n";
                    str += "using System.Threading.Tasks; ";
                    str +="\r\n";
                    string codestr = str + t.Code;
                    codestr = codestr.Replace("System.Threading.Tasks.", "");
                    codestr = codestr.Replace("Microsoft.AspNetCore.Mvc.", "");
                    codestr = codestr.Replace("Microsoft.AspNetCore.Mvc.", "");
                    var model = CheckWriteMyTypeToFile(p,ControllerClassName, codestr);
                    if (model.Id.IsNullOrEmpty())
                    {
                        IsFirst = false;
                        modellist.Add(model);
                    }
                }
            }
            var res = new { 

                Data = modellist,
                Success = true, 
                IsFirst = IsFirst 
            };
            return res;
        }

        /// <summary>
        /// 二次确认生成api
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        public async Task<object> ReBuildCodeAsOpenAPI([FromBody] List<string> list)
        {
            List<Base_ApiList> modellist = new List<Base_ApiList>();
            System.Net.WebClient wclient = new System.Net.WebClient();
            var document = await OpenApiDocument.FromJsonAsync(wclient.DownloadString("http://localhost:5000/swagger/v1/swagger.json"));
            wclient.Dispose();
            var settings = new CSharpControllerGeneratorSettings
            {
                ClassName = "{controller}Controller",
                CSharpGeneratorSettings =
                {
                    Namespace = "MyNamespace",
                },

                ControllerTarget = CSharpControllerTarget.AspNetCore,
                ControllerBaseClass = "Microsoft.AspNetCore.Mvc.Controller",
                //设置多个控制器客户端代码生成
                OperationNameGenerator=new MultipleClientsFromFirstTagAndOperationIdGenerator(),
                GenerateDtoTypes=true

            };

            var generator2 = new MultiCSharpControllerGenerator(document, settings);

            ////生成实体类文件
            //foreach (var t in generator2.GenerateDtoTypes())
            //{
            //    JsonOperateService.WriteMyTypeToEntityFile(t.TypeName, t.Code);
            //}

            foreach (var p in list)
            {
                string ControllerClassName = generator2.GetControllerClassName(p);
                var qq = generator2.GenerateAllClientTypes_(p, ControllerClassName, null);
                foreach (var t in qq)
                {
                    string str = string.Empty;
                    str += "using Coldairarrow.Api.Models;";
                    str +="\r\n";
                    str += "using Microsoft.AspNetCore.Mvc;";
                    str +="\r\n";
                    str += "using System.Threading.Tasks; ";
                    str +="\r\n";
                    string codestr = str + t.Code;
                    codestr = codestr.Replace("System.Threading.Tasks.", "");
                    codestr = codestr.Replace("Microsoft.AspNetCore.Mvc.", "");
                    codestr = codestr.Replace("Microsoft.AspNetCore.Mvc.", "");
                    var model = ReCheckWriteMyTypeToFile(p, ControllerClassName, codestr);
                    if (model.Id.IsNullOrEmpty())
                    {
                        modellist.Add(model);
                    }
                }
            }
            var res = new
            {
                Success = true,
                Data = modellist
            };
            return res;
        }

        /// <summary>
        /// 创建文件
        /// </summary>
        /// <param name="name"></param>
        /// <param name="typename"></param>
        /// <param name="code"></param>

        private Base_ApiList CheckWriteMyTypeToFile(string name, string typename,string code)
        {
            Base_ApiList model = new Base_ApiList();
            model.Tags = name;
            model.CreateTime = DateTime.Now;
            model.Remark = typename;
            model.ControllerClassName = typename;
            model.Deleted = false;
            var ischeck = _db.GetIQueryable<Base_ApiList>().Where(x =>x.Tags==name&&x.ControllerClassName==typename).OrderByDescending(e => e.CreateTime).LastOrDefault();
            if (ischeck==null)
            {
                string path = @"D:\TestNSwag\Coldairarrow.Api\"+name+"\\";
                if (!Directory.Exists(path))
                {
                    DirectoryInfo di = Directory.CreateDirectory(path);
                }
                var filepath = Path.Combine(path, $"{typename}.cs");
                model.Id = IdHelper.GetId();
                model.Path = filepath;
                using (StreamWriter writer = File.CreateText(filepath))
                {
                    writer.Write(code);
                }
                _db.Insert(model);
            }

            return model;
        }

        /// <summary>
        /// 创建文件
        /// </summary>
        /// <param name="name"></param>
        /// <param name="typename"></param>
        /// <param name="code"></param>

        private Base_ApiList ReCheckWriteMyTypeToFile(string name, string typename, string code)
        {
            Base_ApiList model = new Base_ApiList();

            string path = @"D:\TestNSwag\Coldairarrow.Api\"+name+"\\";
            if (!Directory.Exists(path))
            {
                DirectoryInfo di = Directory.CreateDirectory(path);
            }
            var filepath = Path.Combine(path, $"{typename}.cs");
            model.Tags = name;
            model.CreateTime = DateTime.Now;
            model.Remark = typename;
            model.Path = filepath;
            model.ControllerClassName = typename;
            model.Deleted = false;
            model.Id = IdHelper.GetId();
            using (StreamWriter writer = File.CreateText(filepath))
            {
                writer.Write(code);
            }
            _db.Insert(model);

            return model;
        }
        /// <summary>
        /// 创建文件
        /// </summary>
        /// <param name="method"></param>
        /// <param name="name"></param>
        /// <param name="typename"></param>
        /// <param name="code"></param>
        /// <param name="check"></param>
        /// <param name="apiurl"></param>
        /// <param name="summary"></param>
        private Base_ApiList CheckWriteMyTypeToFile(string method, string name,string typename, string code,Boolean check,string apiurl,string summary)
        {
            Base_ApiList model = new Base_ApiList();
            string path = @"D:\TestNSwag\Coldairarrow.Api\";
            if (!Directory.Exists(path))
            {
                DirectoryInfo di = Directory.CreateDirectory(path);
            }
            var filepath = Path.Combine(path, $"{typename}.cs");
            model.ApiUrl = apiurl;
            model.Method =method;
            model.Tags = name;
            model.CreateTime = DateTime.Now;
            model.Remark = typename;
            model.Path = filepath;
            model.ControllerClassName = typename;
            model.Deleted = false;
            model.Summary = summary;
            if (check == true)
            {
                var ischeck = _db.GetIQueryable<Base_ApiList>().Where(x =>x.Method == method&&x.ApiUrl==apiurl&& x.Path==filepath&&x.Tags==name&&x.ControllerClassName==typename).OrderByDescending(e=>e.CreateTime).LastOrDefault();
                if (ischeck==null)
                {
                    model.Id = IdHelper.GetId();
                    using (StreamWriter writer = File.CreateText(filepath))
                    {
                        writer.Write(code);
                    }
                    _db.Insert(model);
                }
            }
            else
            {
                model.Id = IdHelper.GetId();
                using (StreamWriter writer = File.CreateText(filepath))
                {
                    writer.Write(code);
                }
                _db.Insert(model);
            }
            return model;
        }
    }
}